import SdkCommand from "../command/sdk.command"
import { ScreenCapturer, ScreenshotExecutor, ClassFactory, isPositon, isNum } from "./utils"

class EquirectangularExecutor {
  Viewmode: any
  requestTarget: any
  encodeRenderTarget: any
  jpegAsBase64: any
  getXmp: any
  getOrientedAngleTo: any
  forward: any
  sweepForward: any
  viewForward: any
  static equirectangularRes: any
  constructor(e, t, o) {
    this.Viewmode = t.Viewmode
    this.requestTarget = o.requestTarget
    this.encodeRenderTarget = o.encodeRenderTarget
    this.jpegAsBase64 = o.jpegAsBase64
    this.getXmp = o.getXmp
    this.getOrientedAngleTo = o.getOrientedAngleTo
    this.forward = new e.Vector3(0, 0, -1)
    this.sweepForward = new e.Vector3()
    this.viewForward = new e.Vector3()
  }
  validateInput(e) {
    return e
  }
  async exec(e, t, o, n, r, a, s) {
    if (!a.currentSweep || r.currentMode !== this.Viewmode.Panorama) throw new Error("Can only capture equirectangular projections while stationary in a sweep")
    const i = o.getScene().camera,
      d = a.getSweep(a.currentSweep),
      c = await s.load(d)
    this.sweepForward.copy(this.forward), this.sweepForward.copy(this.forward).applyQuaternion(d.rotation).setY(0)
    const u = this.getOrientedAngleTo(this.sweepForward, i.getWorldDirection(this.viewForward).setY(0)) + Math.PI,
      p = await this.requestTarget()
    p.setSize(EquirectangularExecutor.equirectangularRes.width, EquirectangularExecutor.equirectangularRes.height), n.renderEquirectangular(c, p.target, u)
    const m = await this.encodeRenderTarget(p, this.getXmp(p.width, p.height, 0, 0))
    t.return(this.jpegAsBase64(m))
  }
}
EquirectangularExecutor.equirectangularRes = { width: 4096, height: 2048 }

class WorldToScreen {
  issueCommand: any
  GetScreenPositionCommand: any
  constructor(e, t) {
    this.issueCommand = t.issueCommand
    this.GetScreenPositionCommand = e.GetScreenPositionCommand
  }
  validateInput(e) {
    if (!isPositon(e.worldPosition))
      throw Error(`Renderer.getScreenPosition: 'worldPosition' was specified but was not a valid Vector3; got ${e.worldPosition}`)
    return e
  }
  async exec(e, t) {
    const o = await this.issueCommand(new this.GetScreenPositionCommand(e))
    t.return(o)
  }
}
class WorldPositionExecutor {
  GetFloorIntersectCommand: any
  issueCommand: any
  constructor(e, t) {
    this.GetFloorIntersectCommand = e.GetFloorIntersectCommand
    this.issueCommand = t.issueCommand
  }
  validateInput(e) {
    if (
      !(function (e) {
        if (e && "object" == typeof e && "x" in e && "y" in e) {
          const t = e
          return isNum(t.x) && isNum(t.y)
        }
        return !1
      })(e.screenPosition)
    )
      throw Error(`Renderer.getWorldPositionData: 'screenPosition' was not a valid Vector2; got ${e.screenPosition}`)
    return e
  }
  async exec(e, t, o) {
    const n = await this.issueCommand(new this.GetFloorIntersectCommand(e)),
      r = o.getFloorAtIndex(n.floorIndex)
    r
      ? t.return({ position: n.position, floorInfo: { id: r.id, sequence: r.index }, floor: n.floorIndex })
      : t.return({ position: n.position, floorInfo: { id: "", sequence: -1 }, floor: -1 })
  }
}
export default {
  takeScreenShot: (sdk, THREE, exportOBJ, allFunc, dependencies) => {
    const a = new ScreenCapturer(new THREE.Camera(), allFunc.encodeRenderTarget),
      s = new ClassFactory(ScreenshotExecutor, a, exportOBJ, allFunc),
      i = SdkCommand.create(dependencies, s)
    sdk.addCommandToInterface({ namespace: "Renderer", name: "takeScreenShot", args: ["resolution", "visibleObjects", "returnType"] }, i)
  },
  takeEquirectangular: (sdk, THREE, exportOBJ, allFunc, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(EquirectangularExecutor, THREE, exportOBJ, allFunc))
    sdk.addCommandToInterface({ namespace: "Renderer", name: "takeEquirectangular", args: [] }, command)
  },
  getScreenPosition: (sdk, exportOBJ, allFunc, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(WorldToScreen, exportOBJ, allFunc))
    sdk.addCommandToInterface({ namespace: "Renderer", name: "getScreenPosition", args: ["worldPosition"] }, command)
  },
  getWorldPositionData: (sdk, exportOBJ, allFunc, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(WorldPositionExecutor, exportOBJ, allFunc))
    sdk.addCommandToInterface(
      {
        namespace: "Renderer",
        name: "getWorldPositionData",
        args: ["screenPosition", "height", "includeHiddenFloors"]
      },
      command
    )
  }
}
